avoid overhead of fcntl when setting close-on-exec
authorJoey Hess <joeyh@joeyh.name>
Thu, 4 Sep 2025 19:04:03 +0000 (15:04 -0400)
committerJoey Hess <joeyh@joeyh.name>
Thu, 4 Sep 2025 19:04:03 +0000 (15:04 -0400)
unix-2.8.0 adds cloexec to OpenFileFlags, rather than needing to call
setFdOption after opening.

This also might avoid a race, if another thread started a process at
just the wrong time, before the flag got set, it could inherit the FD.

Unfortunately, the arm64-ancient build needs support for older versions
of unix than that, so had to ifdef. That build is still needed to
support using git-annex in termux on phones like mine, I have confirmed
today.

Sponsored-by: Luke T. Shumaker
Git/LockFile.hs
Utility/LockFile/Posix.hs

index 70d8e5bb540d3a98e7028c005cffe00ec0921ce2..9d9042f45357c87708ee909e5501c0eea77b68b8 100644 (file)
@@ -53,8 +53,12 @@ openLock' lck = do
 #ifndef mingw32_HOST_OS
        -- On unix, git simply uses O_EXCL
        h <- openFdWithMode (fromOsPath lck) ReadWrite (Just 0O666)
+#if MIN_VERSION_unix(2,8,0)
+               (defaultFileFlags { exclusive = True, cloexec = True })
+#else
                (defaultFileFlags { exclusive = True })
        setFdOption h CloseOnExec True
+#endif
 #else
        -- It's not entirely clear how git manages locking on Windows,
        -- since it's buried in the portability layer, and different
index f74e3691a7a8cdbf2860581d9ca3d00c787da3c5..3ad3554a8b4fe8a36ebebed7cfcfccad735a13dd 100644 (file)
@@ -5,6 +5,8 @@
  - License: BSD-2-clause
  -}
 
+{-# LANGUAGE CPP #-}
+
 module Utility.LockFile.Posix (
        LockHandle,
        lockShared,
@@ -76,8 +78,13 @@ tryLock lockreq mode lockfile = uninterruptibleMask_ $ do
 openLockFile :: LockRequest -> Maybe ModeSetter -> LockFile -> IO Fd
 openLockFile lockreq filemode lockfile = do
        l <- applyModeSetter filemode lockfile $ \filemode' ->
-               openFdWithMode (fromOsPath lockfile) openfor filemode' defaultFileFlags
+               openFdWithMode (fromOsPath lockfile) openfor filemode' $
+#if MIN_VERSION_unix(2,8,0)
+                       defaultFileFlags { cloexec = True }
+#else
+                       defaultFileFlags
        setFdOption l CloseOnExec True
+#endif
        return l
   where
        openfor = case lockreq of